<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>

    /*
      重新定义数组的原型
    */
    let oldArrayPrototype = Array.prototype;
    // 创建新对象，原型指向oldArrayPrototype， 再扩展新的方法不会影响原型；
    let arrProto = Object.create(oldArrayPrototype);
    ['push', 'pop', 'slice'].forEach(methodName => {
      arrProto[methodName] = function () {
        updateView() // 触发视图
        oldArrayPrototype[methodName].call(this, ...arguments);
      }
    })

    function updateView() {
      console.log('视图更新了！')
    }

    function definReactive(target, key, value) {
      observer(value)
      Object.defineProperty(target, key, {
        get() {
          return value
        },
        set(newVal) {
          if (newVal !== value) {
            // observer(newVal) // 更改对象视图
            value = newVal; // value一直在闭包环境中，再get也能获取到新的值
            updateView()
          }
        }
      })
    }

    function observer(target) {

      if (typeof target !== 'object' || target === null) {
        // 不是对象或者数组
        return target;
      }
      //

      if (Array.isArray(target)) {
        target.__proto__ = arrProto
      }

      // console.log(target)
      for (let key in target) {
        definReactive(target, key, target[key])
      }
    }

    const data = {
      name: 'zhangsan',
      age: '22222',
      info: { address: '88' },
      arr: []
    }

    observer(data);


    // data.name = 'name';
    // data.age = 12;
    // data.age = { name: 12 };
    // data.age.name = 13;
    // data.x = '122'; // 新增属性，vue监听不到，所有有Vue,set
    // delete data.name // 删除属性，监听不到，所有有了Vue.delete

    // data.info.address = '长三角' // 深度监听
    // data.arr.push(23) // 监听数组

    // 如何深度监听

    // 如何监听数组变化

  </script>
</body>

</html>